#include "qb_com.h"

#include <Shlwapi.h>
#include <shlobj.h>

#include "qb_def.h"
#pragma comment(lib, "shell32.lib")
#pragma comment(lib, "shlwapi.lib")
#pragma warning(disable : 4996 4995)

namespace qb {
QbCom::QbCom(void) {
  _hDLL = NULL;
  _lpDllGetClassObject = NULL;
}

QbCom::~QbCom(void) { Unload(); }

int32_t QbCom::Load(LPCTSTR lpDLL) {
  if (!_hDLL) {
    TCHAR szPath[MAX_PATH] = {0};
    GetPath(szPath, lpDLL);
    // 加载DLL并获取对象
    _hDLL = LoadLibrary(szPath);
    if (_hDLL != NULL) {
      _lpDllGetClassObject =
          (DLLGETCLASSOBJECT)GetProcAddress(_hDLL, "QtDllGetClassObject");
    }
    if (!_lpDllGetClassObject) {
      _lpDllGetClassObject =
          (DLLGETCLASSOBJECT)GetProcAddress(_hDLL, "_QtDllGetClassObject@12");
    }

    return _lpDllGetClassObject != NULL ? 0 : -1;
  }
  return 0;
}

int32_t QbCom::CreateInstance(const CLSID& clsid, const IID& iid, void** ppv) {
  if (_lpDllGetClassObject) {
    CComPtr<IClassFactory> lpFactory;
    if (SUCCEEDED(_lpDllGetClassObject(clsid, IID_IClassFactory,
                                       (void**)&lpFactory))) {
      return SUCCEEDED(lpFactory->CreateInstance(NULL, iid, ppv)) ? 0 : -1;
    }
  }
  return -1;
}

int32_t QbCom::Unload() {
  if (_hDLL) {
    _lpDllGetClassObject = NULL;
    if (!FreeLibrary(_hDLL)) {
      return -1;
    }
    _hDLL = NULL;
  }
  return 0;
}

void QbCom::GetPath(TCHAR szPath[MAX_PATH]) {
  ::GetModuleFileName(g_hModule, szPath, MAX_PATH);
  ::PathRemoveFileSpec(szPath);
  ::PathAddBackslash(szPath);
}

void QbCom::GetPath(TCHAR szPath[MAX_PATH], LPCTSTR lpFilename) {
  GetPath(szPath);
  ::PathAppend(szPath, lpFilename);
}
}  // namespace qb
#pragma warning(default : 4996 4995)
